package com.redteam.models;

import com.redteam.data.beans.Airplane;
import com.redteam.data.beans.CharterPilot;
import com.redteam.data.beans.CustomerPilot;
import com.redteam.data.beans.Instructor;
import com.redteam.data.beans.MaintenanceMemo;
import com.redteam.data.beans.Person;
import com.redteam.data.beans.Pilot;
import com.redteam.data.beans.RentalItem;
import com.redteam.data.beans.Reservation;
import com.redteam.data.beans.Simulator;
import com.redteam.data.beans.Student;
import com.redteam.data.dao.AirplaneDAO;
import com.redteam.data.dao.CharterPilotDAO;
import com.redteam.data.dao.InstructorDAO;
import com.redteam.data.dao.MaintenanceMemoDAO;
import com.redteam.data.dao.MechanicDAO;
import com.redteam.data.dao.PersonsDAO;
import com.redteam.data.dao.ReservationDAO;
import com.redteam.data.dao.SimulatorDAO;
import com.redteam.data.dao.StudentDAO;
import com.redteam.data.dao.interfaces.DAO;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Model class that works with the DAOs
 * @author Franco Morales
 */
public class DAOAccessor {

    List<Object> objs;
    DAO dao;

    /**
     * A helper method for getting all the members of a particular type in the database tables
     * @param dao
     * @return A list of objects
     */
    public List<Object> daoGetAll(DAO dao) {
        try {
            objs = dao.getAll();
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return objs;
    }

    public Airplane getPlane(Map<String, String[]> planeMap) {
        List<Airplane> planes = getAllPlanes();
        Airplane plane = null;
        Long planeId;
        for (Airplane p : planes) {
            planeId = Long.parseLong(planeMap.get("plane")[0]);
            if (p.getId() == planeId) {
                plane = p;
            }
        }
        return plane;
    }

    public Student getStudent(Map<String, String[]> studentMap) {
        List<Student> students = getAllStudents();
        Student student = null;
        Long studentId;
        for (Student p : students) {
            studentId = Long.parseLong(studentMap.get("plane")[0]);
            if (p.getId() == studentId) {
                student = p;
            }
        }
        return student;
    }

    /**
     * Returns a list of Airplanes
     * @return A list of Airplanes
     */
    public List<Airplane> getAllPlanes() {
        List<Airplane> planes = null;

        dao = AirplaneDAO.getInstance();
        objs = daoGetAll(dao);

        for (Object o : objs) {
            planes.add((Airplane) o);
        }
        return planes;
    }

    /**
     *
     * @return
     */
    public List<Reservation> getAllReservations() {
        List<Reservation> reservations = null;

        dao = ReservationDAO.getInstance();

        objs = daoGetAll(dao);
        for (Object o : objs) {
            reservations.add((Reservation) o);
        }
        return reservations;
    }

    /**
     * 
     * @return
     */
    public List<Simulator> getAllSimulators() {
        List<Simulator> sims = null;

        dao = SimulatorDAO.getInstance();

        objs = daoGetAll(dao);
        for (Object o : objs) {
            sims.add((Simulator) o);
        }
        return sims;
    }

    public List<Student> getAllStudents() {
        List<Student> students = null;

        dao = StudentDAO.getInstance();

        objs = daoGetAll(dao);
        for (Object o : objs) {
            students.add((Student) o);
        }
        return students;
    }

    /**
     * Returns a list of CharterPilots that can fly a particular Airplane
     * @param parameters
     * @return A list of CharterPilots
     */
    public List<CharterPilot> getCharterPilotsForPlane(Map<String, String[]> parameters) {
        List<CharterPilot> pilots = null;
        List<Airplane> planes = getAllPlanes();

        Airplane plane = null;

        dao = CharterPilotDAO.getInstance();
        objs = daoGetAll(dao);

        Long planeId = Long.parseLong(parameters.get("plane")[0]);
        for (Airplane a : planes) {
            if (a.getId() == planeId) {
                plane = a;
                break;
            }
        }
        for (Object o : objs) {
            pilots.add((CharterPilot) o);
        }
        for (CharterPilot p : pilots) {
            for (String e : plane.getEndorsements()) {
                if (!p.getEndorsements().contains(e)) {
                    pilots.remove(p);
                }
            }
        }
        return pilots;
    }

    /**
     * Returns a list of Instructors that can fly a particular Airplane
     * @param parameters
     * @return A list of Instructors
     */
    public List<Instructor> getInstructorsForPlane(Map<String, String[]> parameters) {
        List<Instructor> instructors = null;
        List<Airplane> planes = getAllPlanes();

        Airplane plane = null;

        dao = InstructorDAO.getInstance();
        objs = daoGetAll(dao);

        Long planeId = Long.parseLong(parameters.get("plane")[0]);
        for (Airplane a : planes) {
            if (a.getId() == planeId) {
                plane = a;
                break;
            }
        }
        for (Object o : objs) {
            instructors.add((Instructor) o);
        }
        for (Instructor i : instructors) {
            for (String e : plane.getEndorsements()) {
                if (!i.getEndorsements().contains(e)) {
                    instructors.remove(i);
                }
            }
        }
        return instructors;
    }

    /**
     *
     * @param parameters
     * @return
     */
    public List<Reservation> getCustomerPilotItemSchedules(Map<String, Reservation> parameters) {
        List<Reservation> allReservations = null;
        List<Reservation> relevantReservations = null;
        Person reserver = null;
        Pilot pilot = null;
        RentalItem item = null;

        allReservations = getAllReservations();

        Reservation res = parameters.get("reservation");
        reserver = res.getReserver();
        pilot = res.getPilot();
        item = res.getRentalItem();
        for (Reservation r : allReservations) {
            if (r.getPilot() == pilot || r.getReserver() == reserver || r.getRentalItem() == item) {
                relevantReservations.add(r);
            }
        }
        return relevantReservations;
    }

    /**
     *
     * @param reservation
     * @return
     */
    public List<Reservation> getCustomerPilotItemSchedules(Reservation reservation) {
        List<Reservation> allReservations = getAllReservations();
        List<Reservation> relevantReservations = null;
        Person reserver = null;
        Pilot pilot = null;
        RentalItem item = null;

        reserver = reservation.getReserver();
        pilot = reservation.getPilot();
        item = reservation.getRentalItem();
        for (Reservation r : allReservations) {
            if (r.getPilot() == pilot || r.getReserver() == reserver || r.getRentalItem() == item) {
                relevantReservations.add(r);
            }
        }
        return relevantReservations;
    }

    /**
     *
     * @param maintenanceMap
     * @return
     */
    public List<MaintenanceMemo> getMaintenanceMemosForPlane(Map<String, String[]> maintenanceMap) {
        List<MaintenanceMemo> allMemos = null;
        List<MaintenanceMemo> relevantMemos = null;

        Airplane plane = null;

        dao = MaintenanceMemoDAO.getInstance();

        objs = daoGetAll(dao);

        for (Object o : objs) {
            allMemos.add((MaintenanceMemo) o);
        }
        Long memoId = Long.parseLong(maintenanceMap.get("memo")[0]);
        for (MaintenanceMemo m : allMemos) {
            if (m.getAirplane().getId() == memoId) {
                relevantMemos.add(m);
            }
        }
        return relevantMemos;
    }

    /**
     *
     * @param personMap
     * @return
     */
    public List<Reservation> getReservationsForPerson(Map<String, String[]> personMap) {
        List<Reservation> allReservations = null;
        List<Reservation> relevantReservations = null;

        dao = ReservationDAO.getInstance();

        allReservations = getAllReservations();

        Long personId = Long.parseLong(personMap.get("person")[0]);
        for (Reservation r : allReservations) {
            if (r.getReserver().getId() == personId) {
                relevantReservations.add(r);
            }
        }
        return relevantReservations;
    }

    public int updateReservationState(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();

        dao = ReservationDAO.getInstance();

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                r.setReservationState(reservationMap.get("state")[0]);
                try {
                    dao.update(r);
                } catch (SQLException ex) {
                    Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 1;
            }
        }
        return 0;
    }

    /**
     *
     * @param reservationMap
     * @return
     */
    public Person getReserverForReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();
        Person person = null;

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                person = r.getReserver();
            }
        }
        return person;
    }

    /**
     *
     * @param reservationMap
     * @return
     */
    public RentalItem getItemForReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();
        RentalItem item = null;

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                item = r.getRentalItem();
            }
        }
        return item;
    }

    /**
     *
     * @param reservationMap
     * @return
     */
    public Pilot getPilotForReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();
        Pilot pilot = null;

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                pilot = r.getPilot();
            }
        }
        return pilot;
    }

    /**
     *
     * @param reservationMap
     * @param state
     * @return
     */
    public int updateReservation(Map<String, String[]> reservationMap) {
        List<Reservation> reservations = getAllReservations();

        Long resId = Long.parseLong(reservationMap.get("reservation")[0]);
        for (Reservation r : reservations) {
            if (r.getId() == resId) {
                r.setReservationState(reservationMap.get("state")[0]);
                return 1;
            }
        }
        return 0;
    }

    /**
     *
     * @param engineerMap
     * @return
     */
    public List<MaintenanceMemo> getMaintenanceMemoForEngineer(Map<String, String[]> engineerMap) {
        List<MaintenanceMemo> allMemos = null;
        List<MaintenanceMemo> relevantMemos = null;

        dao = MechanicDAO.getInstance();

        objs = daoGetAll(dao);
        for (Object o : objs) {
            allMemos.add((MaintenanceMemo) o);
        }
        Long maintEngId = Long.parseLong(engineerMap.get("engineer")[0]);
        for (MaintenanceMemo m : allMemos) {
            if (m.getMechanic().getId() == maintEngId) {
                relevantMemos.add(m);
            }
        }
        return relevantMemos;
    }

    public int submitReservation(Map<String, Reservation> reservationMap) {
        dao = ReservationDAO.getInstance();
        Reservation reservation = reservationMap.get("reservation");
        try {
            return dao.insert(reservation);
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public int revokeStudentEndorsement(Map<String, String[]> studentMap) {
        List<Student> students = getAllStudents();
        List<String> endorsements = null;
        dao = StudentDAO.getInstance();
        Student student = null;

        Long studentId = Long.parseLong(studentMap.get("student")[0]);
        for (Student s : students) {
            if (s.getId() == studentId) {
                student = s;
            }
        }
        endorsements = student.getEndorsements();
        endorsements.remove(studentMap.get("endorsement")[0]);
        student.setEndorsements(endorsements);
        try {
            dao.insert(student);
            return 1;
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public int addStudentEndorsement(Map<String, String[]> studentMap) {
        List<Student> students = null;
        List<String> endorsements = null;
        dao = StudentDAO.getInstance();
        objs = daoGetAll(dao);
        Student student = null;

        for (Object o : objs) {
            students.add((Student) o);
        }
        Long studentId = Long.parseLong(studentMap.get("student")[0]);
        for (Student s : students) {
            if (s.getId() == studentId) {
                student = s;
            }
        }
        endorsements = student.getEndorsements();
        endorsements.add(studentMap.get("endorsement")[0]);
        student.setEndorsements(endorsements);
        try {
            dao.insert(student);
            return 1;
        } catch (SQLException ex) {
            Logger.getLogger(DAOAccessor.class.getName()).log(Level.SEVERE, null, ex);
        }
        return 0;
    }

    public List<Pilot> getAllPilots() {
        List<Pilot> pilots = null;
        dao = PersonsDAO.getInstance();

        objs = daoGetAll(dao);
        for (Object o : objs) {
            if (((Person) o).getDiscriminator().getShortHand().equals("pilot")) {
                pilots.add((CustomerPilot) o);
            } else if (((Person) o).getDiscriminator().getShortHand().equals("stud")) {
                pilots.add((Student) o);
            } else if (((Person) o).getDiscriminator().getShortHand().equals("instr")) {
                pilots.add((Instructor) o);
            } else if (((Person) o).getDiscriminator().getShortHand().equals("ch")) {
                pilots.add((CharterPilot) o);
            }
        }
        return pilots;
    }

    public List<Airplane> getPlanesForPilot(Pilot pilot) {
        List<Airplane> planes = getAllPlanes();

        for (Airplane a : planes) {
            for (String e : pilot.getEndorsements()) {
                if (!a.getEndorsements().contains(e)) {
                    planes.remove(a);
                }
            }
        }
        return planes;
    }
}
